名副其实

变量、函数或类的名称应该已经答复了所有的大问题,它该告诉你,它为什么存在、它做什么事、应该怎么用,如果名称需要注释来补充,那就需要考虑重新命名了。

看下面这段代码:

1
2
3
4
5
6
7
8
9
public List<int[]> getThemne() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList) {
if (x[0] == 4) {
list1.add(x);
}
return list1;
}
}

为什么难以说明上述代码在做什么呢?里面并没有复杂的表达式,只用到三个变量和两个常量,问题不在于代码的简洁度而在于代码的模糊度,即上下文在代码中未被明确体现的程度。上述代码要求我们了解类似以下的一些问题:

  • theList中是什么类型的东西
  • theList零下标条目的意义
  • 4代表什么
  • 我怎么使用返回的列表

    问题的答案并没有体现在代码中,此时我们应该考虑对名字做修改以使得从名称中就能知道我们想了解的一些问题答案:

1
2
3
4
5
6
7
8
9
public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard) {
if (cell[STATUS_VALUE] == FLAGGED) {
flaggedCells.add(cell);
}
return flaggedCells;
}
}

避免误导

避免使用不同之处较小的名称

做有意义的区分

Variable一词永远不应当出现在变量名中,Table一词永远不应当出现在表名中。

使用读得出来的名称

使用可搜索的名称

单字母名称应当仅用于短方法中的本地变量,名称长短应与其作用域大小相对应,若变量或常量可能在代码中多处使用,则应赋其以便于搜索的名称。

看下面这段代码:

1
2
3
for (int i = 0; i < 34; i++) {
s += (t[i] * 4) / 5;
}

我们对其改成如下:

1
2
3
4
5
6
7
8
int realDaysPerIdealDay = 4;
const int WORK_DAYS_PER_WEEK = 5;
int sum = 0;
for (int i = 0; i < NUMBER_OF_TASKS; i++) {
int realTaskDays = taskEstimate[j] * realDaysPerIdealDay;
int realTaskWeeks = (realDays / WORK_DAYS_PER_WEEK);
sum += realTaskWeeks;
}

需要注意的是上面这段代码中sum并非特别有用的名称,不过它至少可以搜索的到。

成员前缀

不必用m_前缀来标明成员变量。

接口和实现

最好使用不加修饰的接口,比如你有一个接口和其实现类,你可能会在接口名称前面加上I表示其为一个接口,但是前导字母I被滥用到了说好听点是干扰,说难听点根本就是废话的程度,我不想让客户知道我给他们的是接口,我就想让他们知道那是一个具体的实现,如果接口和实现必须选一个来编码的话,我宁愿选择实现,举个例子:

ShapeFactoryShapeFactoryImpl组合永远都比IShapeFactoryShapeFactory组合好。

类名

类名和对象名应当是名词或名词短语,如Customer、WikiPage、Account和AddressParser,避免使用Manager、Processor、Data或Info这样的类名,类名不应当是动词。

方法名

方法名应当是动词或动词短语,如postPayment、deletePage或save。

重载构造器时,使用描述了参数的静态工厂方法名,例如:

1
Complex fulcrumPoint = Complex.FromRealNumber(23.0);

通常好于:

1
Complex fulcrumPoint = new Complex(23.0);

可以考虑将相应的构造器设置为private,强制使用这种命名手段。

添加有意义的语境

你需要用良好命名的类、函数或名称空间来放置名称,给读者提供语境,如果没这么做,给名称添加前缀也是一种好方法。

设想你有名为firstName、lastName、street、houseNumber、city、state和zipcode的变量,当它们放在一起的时候很明确构成了一个地址,不过假使只是在某个方法中看见单独的一个变量state呢?你会理所当然推断那是某个地址的一部分吗?

可以添加前缀addrFirstName、addrLastName、addrState等,以此提供语境。至少读者会明白这些变量是某个更大结构的一部分。当然,更好的方法是创建名为Address的类,这样,即便是编译器也会知道这些变量隶属某个更大概念了。